Development Models > Imperative Programming Model > Imperative Programming Model for OPC Data (Classic and UA) > Subscribing to Information (OPC Data) > Subscribing to OPC Classic Items |
Subscription is initiated by calling either SubscribeItem or SubscribeMultipleItems method. For any change in the subscribed item’s value, your application will receive the ItemChanged event notification, described further below. Obviously, you first need to hook up event handler for that event, and in order to prevent event loss, you should do it before subscribing. Alternatively, you can pass a callback method into the SubscribeItem or SubscribeMultipleItems call.
Values of some items may be changing quite frequently, and receiving all changes that are generated is not desirable for performance reasons; there are also physical limitations to the event throughput in the system. Your application needs to specify the requested update rate, which effectively tells the OPC server that you do not need to receive event notifications any faster than that. For OPC items that support it, you can optionally specify a percent deadband; only changes that exceed the deadband will generate an event notification.
In QuickOPC.NET, the requested update rate, percent deadband, and data type are all contained in a DAGroupParameters object.
If you want to subscribe to a specific OPC item, call the SubscribeItem method. You can pass in individual arguments for machine name, server class, ItemID, data type, requested update rate, and an optional percent deadband. Usually, you also pass in a State argument of type Object (in QuickOPC.NET) or VARIANT (in QuickOPC-COM). When the item’s value changes, the State argument is then passed to the ItemChanged event handler in the EasyDAItemChangedEventArgs.Arguments.State property. The SubscribeItem method returns a subscription handle that you can later use to change the subscription parameters, or unsubscribe.
// Hooking up events and receiving OPC item changes. using System; using System.Threading; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace DocExamples.DataAccess._EasyDAClient { partial class SubscribeItem { public static void Main1() { // Instantiate the client object. using (var client = new EasyDAClient()) { var eventHandler = new EasyDAItemChangedEventHandler(client_ItemChanged); client.ItemChanged += eventHandler; Console.WriteLine("Subscribing item..."); client.SubscribeItem("", "OPCLabs.KitServer.2", "Demo.Ramp", 200); Console.WriteLine("Process item change notifications for 30 seconds..."); Thread.Sleep(30 * 1000); Console.WriteLine("Unsubscribing all items..."); client.UnsubscribeAllItems(); client.ItemChanged -= eventHandler; } Console.WriteLine("Finished."); } static void client_ItemChanged(object sender, EasyDAItemChangedEventArgs e) { if (e.Succeeded) Console.WriteLine(e.Vtq); else Console.WriteLine($"*** Failure: {e.ErrorMessageBrief}"); } } }
# Hooking up events and receiving OPC item changes. #requires -Version 5.1 using namespace OpcLabs.EasyOpc.DataAccess # The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows . Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcClassicCore.dll" Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcClassic.dll" Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcClassicComponents.dll" # Instantiate the client object. $client = New-Object EasyDAClient # Item changed event handler Register-ObjectEvent -InputObject $client -EventName ItemChanged -Action { if ($EventArgs.Succeeded) { Write-Host $EventArgs.Vtq } else { Write-Host "*** Failure: $($EventArgs.ErrorMessageBrief)" } } Write-Host "Subscribing item..." [IEasyDAClientExtension]::SubscribeItem($client, "", "OPCLabs.KitServer.2", "Demo.Ramp", 200) Write-Host "Processing item changes for 30 seconds..." $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() while ($stopwatch.Elapsed.TotalSeconds -lt 30) { Start-Sleep -Seconds 1 } Write-Host "Unsubscribing items..." $client.UnsubscribeAllItems() Write-Host "Finished."
# Hooking up events and receiving OPC item changes. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.DataAccess import * # Item changed event handler. def itemChanged(sender, e): if e.Succeeded: print(e.Vtq) else: print('*** Failure: ', e.ErrorMessageBrief, sep='') # Instantiate the client object. client = EasyDAClient() client.ItemChanged += itemChanged print('Subscribing item changes...') IEasyDAClientExtension.SubscribeItem(client, '', 'OPCLabs.KitServer.2', 'Demo.Ramp', 200) print('Processing item change notifications for 30 seconds...') time.sleep(30) print('Unsubscribing all items...') client.UnsubscribeAllItems() client.ItemChanged -= itemChanged print('Finished.')
' Hooking up events and receiving OPC item changes. Imports System.Threading Imports OpcLabs.EasyOpc.DataAccess Imports OpcLabs.EasyOpc.DataAccess.OperationModel Namespace DataAccess._EasyDAClient Partial Friend Class SubscribeItem Shared Sub Main1() Using client = New EasyDAClient() Dim eventHandler = New EasyDAItemChangedEventHandler(AddressOf client_ItemChanged) AddHandler client.ItemChanged, eventHandler Console.WriteLine("Subscribing item...") client.SubscribeItem("", "OPCLabs.KitServer.2", "Demo.Ramp", 200) Thread.Sleep(30 * 1000) client.UnsubscribeAllItems() RemoveHandler client.ItemChanged, eventHandler End Using End Sub Private Shared Sub client_ItemChanged(sender As Object, e As EasyDAItemChangedEventArgs) If e.Succeeded Then Console.WriteLine(e.Vtq) Else Console.WriteLine("*** Failure: {0}", e.ErrorMessageBrief) End If End Sub End Class End Namespace
// This example shows how to subscribe to changes of a single item and display the value of the item with each change. type TSubscribeItem_ClientEventHandlers = class // Item changed event handler procedure OnItemChanged( ASender: TObject; sender: OleVariant; const eventArgs: _EasyDAItemChangedEventArgs); end; procedure TSubscribeItem_ClientEventHandlers.OnItemChanged( ASender: TObject; sender: OleVariant; const eventArgs: _EasyDAItemChangedEventArgs); begin if eventArgs.Succeeded then WriteLn(eventArgs.Vtq.ToString) else WriteLn(Format('*** Failure: %s', [eventArgs.ErrorMessageBrief])); end; class procedure SubscribeItem.Main; var Client: TEasyDAClient; ClientEventHandlers: TSubscribeItem_ClientEventHandlers; begin // Instantiate the client object and hook events Client := TEasyDAClient.Create(nil); ClientEventHandlers := TSubscribeItem_ClientEventHandlers.Create; Client.OnItemChanged := ClientEventHandlers.OnItemChanged; Client.SubscribeItem('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000); WriteLn('Processing item changed events for 1 minute...'); PumpSleep(60*1000); WriteLn('Unsubscribing...'); Client.UnsubscribeAllItems; WriteLn('Waiting for 5 seconds...'); PumpSleep(5*1000); WriteLn('Finished.'); FreeAndNil(Client); FreeAndNil(ClientEventHandlers); end;
// This example shows how to subscribe to changes of a single item and display the value of the item with each change. // // Some related documentation: http://php.net/manual/en/function.com-event-sink.php . Pay attention to the comment that says // "Be careful how you use this feature; if you are doing something similar to the example below, then it doesn't really make // sense to run it in a web server context.". What they are trying to say is that processing a web request should be // a short-lived code, which does not fit well with the idea of being subscribed to events and received them over longer time. // It is possible to write such code, but it is only useful when processing the request is allowed to take relatively long. Or, // when you are using PHP from command-line, or otherwise - not to serve a web page directly. // // Subscribing to QuickOPC-COM events in the context of PHP Web application, while not imposing the limitations to the request // processing time, has to be "worked around", e.g. using the "event pull" mechanism. class DEasyDAClientEvents { function ItemChanged($varSender, $varE) { if ($varE->Succeeded) { print $varE->Vtq->ToString(); print "\n"; } else { printf("*** Failure: %s\n", $varE->ErrorMessageBrief); } } } $Client = new COM("OpcLabs.EasyOpc.DataAccess.EasyDAClient"); $Events = new DEasyDAClientEvents(); com_event_sink($Client, $Events, "DEasyDAClientEvents"); $Client->SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000); print "Processing item changed events for 1 minute...\n"; $startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 60);
Rem This example shows how to subscribe to changes of a single item and display the value of the item with each change. ' The client object, with events 'Public WithEvents Client1 As EasyDAClient Private Sub SubscribeItem_Main_Command_Click() OutputText = "" ' Instantiate the client object and hook events Set Client1 = New EasyDAClient OutputText = OutputText & "Subscribing..." & vbCrLf Call Client1.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000) OutputText = OutputText & "Processing item changed events for 1 minute..." & vbCrLf Pause 60000 OutputText = OutputText & "Unsubscribing..." & vbCrLf Client1.UnsubscribeAllItems OutputText = OutputText & "Waiting for 5 seconds..." & vbCrLf Pause 5000 OutputText = OutputText & "Finished." & vbCrLf Set Client1 = Nothing End Sub Public Sub Client1_ItemChanged(ByVal sender As Variant, ByVal eventArgs As EasyDAItemChangedEventArgs) If eventArgs.Succeeded Then OutputText = OutputText & eventArgs.vtq & vbCrLf Else OutputText = OutputText & "*** Failure: " & eventArgs.ErrorMessageBrief & vbCrLf End If End Sub
Rem This example shows how to subscribe to changes of a single item and display the value of the item with each change. Option Explicit Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient") WScript.ConnectObject Client, "Client_" Client.SubscribeItem "", "OPCLabs.KitServer.2", "Simulation.Random", 1000 WScript.Echo "Processing item changed events for 1 minute..." WScript.Sleep 60*1000 Sub Client_ItemChanged(Sender, e) If Not (e.Succeeded) Then WScript.Echo "*** Failure: " & e.ErrorMessageBrief Exit Sub End If WScript.Echo e.Vtq.ToString End Sub
// This example subscribes to changes of 2 items separately, and displays rich information available with each item changed // event notification. using System; using System.Diagnostics; using System.Threading; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace DocExamples.DataAccess._EasyDAItemChangedEventArgs { class General { public static void Main1() { // Instantiate the client object. using (var client = new EasyDAClient()) { var eventHandler = new EasyDAItemChangedEventHandler(client_ItemChanged); client.ItemChanged += eventHandler; Console.WriteLine("Subscribing items..."); client.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 5 * 1000); client.SubscribeItem("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 5 * 1000); Console.WriteLine("Processing item changed events for 1 minute..."); Thread.Sleep(60 * 1000); } } static void client_ItemChanged(object sender, EasyDAItemChangedEventArgs e) { Console.WriteLine(); Console.WriteLine($"e.Arguments.State: {e.Arguments.State}"); Console.WriteLine($"e.Arguments.ServerDescriptor.MachineName: {e.Arguments.ServerDescriptor.MachineName}"); Console.WriteLine($"e.Arguments.ServerDescriptor.ServerClass: {e.Arguments.ServerDescriptor.ServerClass}"); Console.WriteLine($"e.Arguments.ItemDescriptor.ItemId: {e.Arguments.ItemDescriptor.ItemId}"); Console.WriteLine($"e.Arguments.ItemDescriptor.AccessPath: {e.Arguments.ItemDescriptor.AccessPath}"); Console.WriteLine($"e.Arguments.ItemDescriptor.RequestedDataType: {e.Arguments.ItemDescriptor.RequestedDataType}"); Console.WriteLine($"e.Arguments.GroupParameters.Locale: {e.Arguments.GroupParameters.Locale}"); Console.WriteLine($"e.Arguments.GroupParameters.RequestedUpdateRate: {e.Arguments.GroupParameters.RequestedUpdateRate}"); Console.WriteLine($"e.Arguments.GroupParameters.PercentDeadband: {e.Arguments.GroupParameters.PercentDeadband}"); if (e.Succeeded) { Debug.Assert(!(e.Vtq is null)); Console.WriteLine($"e.Vtq.Value: {e.Vtq.Value}"); Console.WriteLine($"e.Vtq.Timestamp: {e.Vtq.Timestamp}"); Console.WriteLine($"e.Vtq.TimestampLocal: {e.Vtq.TimestampLocal}"); Console.WriteLine($"e.Vtq.Quality: {e.Vtq.Quality}"); } else { Debug.Assert(!(e.Exception is null)); Console.WriteLine($"e.Exception.Message: {e.Exception.Message}"); Console.WriteLine($"e.Exception.Source: {e.Exception.Source}"); } } // Example output: // //Processing item changed events for 1 minute... // //e.Arguments.State: //e.Arguments.ServerDescriptor.MachineName: //e.Arguments.ServerDescriptor.ServerClass: OPCLabs.KitServer.2 //e.Arguments.ItemDescriptor.ItemId: Simulation.Random //e.Arguments.ItemDescriptor.AccessPath: //e.Arguments.ItemDescriptor.RequestedDataType: Empty //e.Arguments.GroupParameters.Locale: 0 //e.Arguments.GroupParameters.RequestedUpdateRate: 5000 //e.Arguments.GroupParameters.PercentDeadband: 0 //e.Vtq.Value: 0.00125125888851588 //e.Vtq.Timestamp: 4/10/2020 4:35:25 PM //e.Vtq.TimestampLocal: 4/10/2020 6:35:25 PM //e.Vtq.Quality: GoodNonspecific (192) // //e.Arguments.State: //e.Arguments.ServerDescriptor.MachineName: //e.Arguments.ServerDescriptor.ServerClass: OPCLabs.KitServer.2 //e.Arguments.ItemDescriptor.ItemId: Trends.Ramp(1 min) //e.Arguments.ItemDescriptor.AccessPath: //e.Arguments.ItemDescriptor.RequestedDataType: Empty //e.Arguments.GroupParameters.Locale: 0 //e.Arguments.GroupParameters.RequestedUpdateRate: 5000 //e.Arguments.GroupParameters.PercentDeadband: 0 //e.Vtq.Value: 0.431881904602051 //e.Vtq.Timestamp: 4/10/2020 4:35:25 PM //e.Vtq.TimestampLocal: 4/10/2020 6:35:25 PM //e.Vtq.Quality: GoodNonspecific (192) // //... } }
Rem This example subscribes to changes of 2 items separately, and displays rich information available with each item changed Rem event notification. Option Explicit Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient") WScript.ConnectObject Client, "Client_" Client.SubscribeItem "", "OPCLabs.KitServer.2", "Simulation.Random", 5*1000 Client.SubscribeItem "", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 5*1000 WScript.Echo "Processing item changed events for 1 minute..." WScript.Sleep 60*1000 Sub Client_ItemChanged(Sender, e) On Error Resume Next WScript.Echo WScript.Echo "e.Arguments.State: " & e.Arguments.State WScript.Echo "e.Arguments.ServerDescriptor.MachineName: " & e.Arguments.ServerDescriptor.MachineName WScript.Echo "e.Arguments.ServerDescriptor.ServerClass: " & e.Arguments.ServerDescriptor.ServerClass WScript.Echo "e.Arguments.ItemDescriptor.ItemId: " & e.Arguments.ItemDescriptor.ItemId WScript.Echo "e.Arguments.ItemDescriptor.AccessPath: " & e.Arguments.ItemDescriptor.AccessPath WScript.Echo "e.Arguments.ItemDescriptor.RequestedDataType: " & e.Arguments.ItemDescriptor.RequestedDataType WScript.Echo "e.Arguments.GroupParameters.Locale: " & e.Arguments.GroupParameters.Locale WScript.Echo "e.Arguments.GroupParameters.RequestedUpdateRate: " & e.Arguments.GroupParameters.RequestedUpdateRate WScript.Echo "e.Arguments.GroupParameters.PercentDeadband: " & e.Arguments.GroupParameters.PercentDeadband WScript.Echo "e.Exception.Message: " & e.Exception.Message WScript.Echo "e.Exception.Source: " & e.Exception.Source WScript.Echo "e.Exception.ErrorCode: " & e.Exception.ErrorCode WScript.Echo "e.Vtq.Value: " & e.Vtq.Value WScript.Echo "e.Vtq.Timestamp: " & e.Vtq.Timestamp WScript.Echo "e.Vtq.TimestampLocal: " & e.Vtq.TimestampLocal WScript.Echo "e.Vtq.Quality: " & e.Vtq.Quality End Sub
In QuickOPC.NET, you can also pass in a combination of ServerDescriptor, DAItemDescriptor and DAGroupParameters objects, in place of individual arguments.
The State argument is typically used to provide some sort of correlation between objects in your application, and the event notifications. For example, if you are programming an HMI application and you want the event handler to update the control that displays the item’s value, you may want to set the State argument to the control object itself. When the event notification arrives, you simply update the control indicated by the State property of EasyDAItemChangedEventArgs, without having to look it up by ItemId or so. See Use the state instead of handles to identify subscribed entities.
To subscribe to multiple items simultaneously in an efficient manner, call the SubscribeMultipleItems method (instead of multiple SubscribeItem calls in a loop). You receive back an array of integers, which are the subscription handles.
You pass in an array of DAItemGroupArguments objects (each containing information for a single subscription to be made), to the SubscribeMultipleItems method.
// This example shows how subscribe to changes of multiple items and display the value of the item with each change. using System; using System.Threading; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace DocExamples.DataAccess._EasyDAClient { partial class SubscribeMultipleItems { public static void Main1() { // Instantiate the client object. using (var client = new EasyDAClient()) { client.ItemChanged += client_Main1_ItemChanged; Console.WriteLine("Subscribing item changes..."); client.SubscribeMultipleItems( new[] { new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, null), new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, null), new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, null), new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, null) }); Console.WriteLine("Processing item changed events for 1 minute..."); Thread.Sleep(60 * 1000); Console.WriteLine("Unsubscribing item changes..."); } Console.WriteLine("Finished."); } // Item changed event handler static void client_Main1_ItemChanged(object sender, EasyDAItemChangedEventArgs e) { if (e.Succeeded) Console.WriteLine($"{e.Arguments.ItemDescriptor.ItemId}: {e.Vtq}"); else Console.WriteLine($"{e.Arguments.ItemDescriptor.ItemId} *** Failure: {e.ErrorMessageBrief}"); } } }
# This example shows how subscribe to changes of multiple items and display the value of the item with each change. #requires -Version 5.1 using namespace OpcLabs.EasyOpc.DataAccess using namespace OpcLabs.EasyOpc.DataAccess.OperationModel # The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows . Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcClassicCore.dll" Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcClassic.dll" Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcClassicComponents.dll" # Instantiate the client object. $client = New-Object EasyDAClient # Item changed event handler Register-ObjectEvent -InputObject $client -EventName ItemChanged -Action { if ($EventArgs.Succeeded) { Write-Host "$($EventArgs.Arguments.ItemDescriptor.ItemId): $($EventArgs.Vtq)" } else { Write-Host "$($EventArgs.Arguments.ItemDescriptor.ItemId) *** Failure: $($EventArgs.ErrorMessageBrief)" } } Write-Host "Subscribing item changes..." $handleArray = [IEasyDAClientExtension]::SubscribeMultipleItems($client, @( (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, $null)), (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, $null)), (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, $null)), (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, $null)) )) Write-Host "Processing item changed events for 1 minute..." $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() while ($stopwatch.Elapsed.TotalSeconds -lt 30) { Start-Sleep -Seconds 1 } Write-Host "Unsubscribing item changes..." $client.UnsubscribeAllItems() Write-Host "Finished."
# This example shows how subscribe to changes of multiple items and display the value of the item with each change. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.DataAccess import * from OpcLabs.EasyOpc.DataAccess.OperationModel import * # Item changed event handler. def itemChanged(sender, e): if e.Succeeded: print(e.Arguments.ItemDescriptor.ItemId, ': ', e.Vtq, sep='') else: print(e.Arguments.ItemDescriptor.ItemId, ' *** Failure: ', e.ErrorMessageBrief, sep='') # Instantiate the client object. client = EasyDAClient() client.ItemChanged += itemChanged print('Subscribing item changes...') client.SubscribeMultipleItems([ EasyDAItemSubscriptionArguments('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000, None), EasyDAItemSubscriptionArguments('', 'OPCLabs.KitServer.2', 'Trends.Ramp (1 min)', 1000, None), EasyDAItemSubscriptionArguments('', 'OPCLabs.KitServer.2', 'Trends.Sine (1 min)', 1000, None), EasyDAItemSubscriptionArguments('', 'OPCLabs.KitServer.2', 'Simulation.Register_I4', 1000, None), ]) print('Processing item change notifications for 1 minute...') time.sleep(60) print('Unsubscribing all items...') client.UnsubscribeAllItems() client.ItemChanged -= itemChanged print('Finished.')
' This example shows how subscribe to changes of multiple items and display the value of the item with each change. Imports System.Threading Imports OpcLabs.EasyOpc.DataAccess Imports OpcLabs.EasyOpc.DataAccess.OperationModel Namespace DataAccess._EasyDAClient Partial Friend Class SubscribeMultipleItems Public Shared Sub Main1() Using client = New EasyDAClient() AddHandler client.ItemChanged, AddressOf client_ItemChanged_Main1 client.SubscribeMultipleItems(New DAItemGroupArguments() { _ New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, Nothing), _ New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, Nothing), _ New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, Nothing), _ New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, Nothing) _ }) Console.WriteLine("Processing item changed events for 1 minute...") Thread.Sleep(60 * 1000) End Using End Sub ' Item changed event handler Private Shared Sub client_ItemChanged_Main1(ByVal sender As Object, ByVal e As EasyDAItemChangedEventArgs) ' Display the data If e.Succeeded Then Console.WriteLine("{0}: {1}", e.Arguments.ItemDescriptor.ItemId, e.Vtq) Else Console.WriteLine("{0} *** Failure: {1}", e.Arguments.ItemDescriptor.ItemId, e.ErrorMessageBrief) End If End Sub End Class End Namespace
// This example shows how to subscribe to changes of multiple items and display the value of the item with each change. class DEasyDAClientEvents { function ItemChanged($varSender, $varE) { if ($varE->Succeeded) { printf("s: s\n", $varE->Arguments->ItemDescriptor->ItemId, $varE->Vtq->ToString()); } else { printf("*** Failure: %s\n", $varE->ErrorMessageBrief); } } } $ItemSubscriptionArguments1 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments"); $ItemSubscriptionArguments1->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2"; $ItemSubscriptionArguments1->ItemDescriptor->ItemID = "Simulation.Random"; $ItemSubscriptionArguments1->GroupParameters->RequestedUpdateRate = 1000; $ItemSubscriptionArguments2 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments"); $ItemSubscriptionArguments2->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2"; $ItemSubscriptionArguments2->ItemDescriptor->ItemID = "Trends.Ramp (1 min)"; $ItemSubscriptionArguments2->GroupParameters->RequestedUpdateRate = 1000; $ItemSubscriptionArguments3 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments"); $ItemSubscriptionArguments3->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2"; $ItemSubscriptionArguments3->ItemDescriptor->ItemID = "Trends.Sine (1 min)"; $ItemSubscriptionArguments3->GroupParameters->RequestedUpdateRate = 1000; $ItemSubscriptionArguments4 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments"); $ItemSubscriptionArguments4->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2"; $ItemSubscriptionArguments4->ItemDescriptor->ItemID = "Simulation.Register_I4"; $ItemSubscriptionArguments4->GroupParameters->RequestedUpdateRate = 1000; $arguments[0] = $ItemSubscriptionArguments1; $arguments[1] = $ItemSubscriptionArguments2; $arguments[2] = $ItemSubscriptionArguments3; $arguments[3] = $ItemSubscriptionArguments4; $Client = new COM("OpcLabs.EasyOpc.DataAccess.EasyDAClient"); $Events = new DEasyDAClientEvents(); com_event_sink($Client, $Events, "DEasyDAClientEvents"); $Client->SubscribeMultipleItems($arguments); print "Processing item changed events for 1 minute...\n"; $startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 60);
// This example shows how to subscribe to changes of multiple items and display the value of the item with each change. type TSubscribeMultipleItems_ClientEventHandlers = class // Item changed event handler procedure OnItemChanged( ASender: TObject; sender: OleVariant; const eventArgs: _EasyDAItemChangedEventArgs); end; procedure TSubscribeMultipleItems_ClientEventHandlers.OnItemChanged( ASender: TObject; sender: OleVariant; const eventArgs: _EasyDAItemChangedEventArgs); begin if eventArgs.Succeeded then WriteLn(eventArgs.Arguments.ItemDescriptor.ItemId, ': ', eventArgs.Vtq.ToString) else WriteLn(eventArgs.Arguments.ItemDescriptor.ItemId, ' *** Failure: ', eventArgs.ErrorMessageBrief); end; class procedure SubscribeMultipleItems.Main; var Arguments: OleVariant; Client: TEasyDAClient; ClientEventHandlers: TSubscribeMultipleItems_ClientEventHandlers; HandleArray: OleVariant; ItemSubscriptionArguments1: _EasyDAItemSubscriptionArguments; ItemSubscriptionArguments2: _EasyDAItemSubscriptionArguments; ItemSubscriptionArguments3: _EasyDAItemSubscriptionArguments; ItemSubscriptionArguments4: _EasyDAItemSubscriptionArguments; begin ItemSubscriptionArguments1 := CoEasyDAItemSubscriptionArguments.Create; ItemSubscriptionArguments1.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2'; ItemSubscriptionArguments1.ItemDescriptor.ItemID := 'Simulation.Random'; ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate := 1000; ItemSubscriptionArguments2 := CoEasyDAItemSubscriptionArguments.Create; ItemSubscriptionArguments2.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2'; ItemSubscriptionArguments2.ItemDescriptor.ItemID := 'Trends.Ramp (1 min)'; ItemSubscriptionArguments2.GroupParameters.RequestedUpdateRate := 1000; ItemSubscriptionArguments3 := CoEasyDAItemSubscriptionArguments.Create; ItemSubscriptionArguments3.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2'; ItemSubscriptionArguments3.ItemDescriptor.ItemID := 'Trends.Sine (1 min)'; ItemSubscriptionArguments3.GroupParameters.RequestedUpdateRate := 1000; ItemSubscriptionArguments4 := CoEasyDAItemSubscriptionArguments.Create; ItemSubscriptionArguments4.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2'; ItemSubscriptionArguments4.ItemDescriptor.ItemID := 'Simulation.Register_I4'; ItemSubscriptionArguments4.GroupParameters.RequestedUpdateRate := 1000; Arguments := VarArrayCreate([0, 3], varVariant); Arguments[0] := ItemSubscriptionArguments1; Arguments[1] := ItemSubscriptionArguments2; Arguments[2] := ItemSubscriptionArguments3; Arguments[3] := ItemSubscriptionArguments4; // Instantiate the client object and hook events Client := TEasyDAClient.Create(nil); ClientEventHandlers := TSubscribeMultipleItems_ClientEventHandlers.Create; Client.OnItemChanged := ClientEventHandlers.OnItemChanged; TVarData(HandleArray).VType := varArray or varVariant; TVarData(HandleArray).VArray := PVarArray( Client.SubscribeMultipleItems(Arguments)); WriteLn('Processing item changed events for 1 minute...'); PumpSleep(60*1000); WriteLn('Unsubscribing...'); Client.UnsubscribeAllItems; WriteLn('Waiting for 5 seconds...'); PumpSleep(5*1000); WriteLn('Finished.'); VarClear(HandleArray); VarClear(Arguments); FreeAndNil(Client); FreeAndNil(ClientEventHandlers); end;
Rem This example shows how to subscribe to changes of multiple items and display the value of the item with each change. ' The client object, with events 'Public WithEvents Client2 As EasyDAClient Private Sub SubscribeMultipleItems_Main_Command_Click() OutputText = "" Dim itemSubscriptionArguments1 As New EasyDAItemSubscriptionArguments itemSubscriptionArguments1.serverDescriptor.ServerClass = "OPCLabs.KitServer.2" itemSubscriptionArguments1.ItemDescriptor.itemId = "Simulation.Random" itemSubscriptionArguments1.GroupParameters.requestedUpdateRate = 1000 Dim itemSubscriptionArguments2 As New EasyDAItemSubscriptionArguments itemSubscriptionArguments2.serverDescriptor.ServerClass = "OPCLabs.KitServer.2" itemSubscriptionArguments2.ItemDescriptor.itemId = "Trends.Ramp (1 min)" itemSubscriptionArguments2.GroupParameters.requestedUpdateRate = 1000 Dim itemSubscriptionArguments3 As New EasyDAItemSubscriptionArguments itemSubscriptionArguments3.serverDescriptor.ServerClass = "OPCLabs.KitServer.2" itemSubscriptionArguments3.ItemDescriptor.itemId = "Trends.Sine (1 min)" itemSubscriptionArguments3.GroupParameters.requestedUpdateRate = 1000 ' Intentionally specifying an unknown item here, to demonstrate its behavior. Dim itemSubscriptionArguments4 As New EasyDAItemSubscriptionArguments itemSubscriptionArguments4.serverDescriptor.ServerClass = "OPCLabs.KitServer.2" itemSubscriptionArguments4.ItemDescriptor.itemId = "Simulation.Register_I4" itemSubscriptionArguments4.GroupParameters.requestedUpdateRate = 1000 Dim arguments(3) As Variant Set arguments(0) = itemSubscriptionArguments1 Set arguments(1) = itemSubscriptionArguments2 Set arguments(2) = itemSubscriptionArguments3 Set arguments(3) = itemSubscriptionArguments4 ' Instantiate the client object Set Client2 = New EasyDAClient OutputText = OutputText & "Subscribing item changes..." & vbCrLf Dim handleArray() As Variant handleArray = Client2.SubscribeMultipleItems(arguments) OutputText = OutputText & "Processing item changed events for 1 minute..." & vbCrLf Pause 60000 OutputText = OutputText & "Unsubscribing..." & vbCrLf Client2.UnsubscribeAllItems OutputText = OutputText & "Waiting for 5 seconds..." & vbCrLf Pause 5000 OutputText = OutputText & "Finished." & vbCrLf Set Client2 = Nothing End Sub Public Sub Client2_ItemChanged(ByVal sender As Variant, ByVal eventArgs As EasyDAItemChangedEventArgs) If eventArgs.Succeeded Then OutputText = OutputText & eventArgs.arguments.ItemDescriptor.itemId & ": " & eventArgs.vtq & vbCrLf Else OutputText = OutputText & eventArgs.arguments.ItemDescriptor.itemId & " *** Failure: " & eventArgs.ErrorMessageBrief & vbCrLf End If End Sub
Rem This example shows how to subscribe to changes of multiple items and display the value of the item with each change. Option Explicit Dim ItemSubscriptionArguments1: Set ItemSubscriptionArguments1 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments") ItemSubscriptionArguments1.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2" ItemSubscriptionArguments1.ItemDescriptor.ItemID = "Simulation.Random" ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate = 1000 Dim ItemSubscriptionArguments2: Set ItemSubscriptionArguments2 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments") ItemSubscriptionArguments2.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2" ItemSubscriptionArguments2.ItemDescriptor.ItemID = "Trends.Ramp (1 min)" ItemSubscriptionArguments2.GroupParameters.RequestedUpdateRate = 1000 Dim ItemSubscriptionArguments3: Set ItemSubscriptionArguments3 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments") ItemSubscriptionArguments3.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2" ItemSubscriptionArguments3.ItemDescriptor.ItemID = "Trends.Sine (1 min)" ItemSubscriptionArguments3.GroupParameters.RequestedUpdateRate = 1000 Dim ItemSubscriptionArguments4: Set ItemSubscriptionArguments4 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments") ItemSubscriptionArguments4.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2" ItemSubscriptionArguments4.ItemDescriptor.ItemID = "Simulation.Register_I4" ItemSubscriptionArguments4.GroupParameters.RequestedUpdateRate = 1000 Dim arguments(3) Set arguments(0) = ItemSubscriptionArguments1 Set arguments(1) = ItemSubscriptionArguments2 Set arguments(2) = ItemSubscriptionArguments3 Set arguments(3) = ItemSubscriptionArguments4 Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient") WScript.ConnectObject Client, "Client_" Client.SubscribeMultipleItems arguments WScript.Echo "Processing item changed events for 1 minute..." WScript.Sleep 60*1000 Sub Client_ItemChanged(Sender, e) If Not (e.Succeeded) Then WScript.Echo "*** Failure: " & e.ErrorMessageBrief Exit Sub End If WScript.Echo e.Arguments.ItemDescriptor.ItemId & ": " & e.Vtq End Sub
// This example shows how to store current state of the subscribed items in a dictionary. using System; using System.Collections.Generic; using System.Threading; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace DocExamples.DataAccess._EasyDAClient { partial class SubscribeMultipleItems { public static void StoreInDictionary() { // Instantiate the client object. using (var client = new EasyDAClient()) { client.ItemChanged += client_ItemChanged_StoreInDictionary; Console.WriteLine("Subscribing item changes..."); client.SubscribeMultipleItems( new[] { new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, null), new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, null), new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, null), new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, null) }); Console.WriteLine("Processing item changed events for 1 minute..."); int startTickCount = Environment.TickCount; do { Thread.Sleep(5*1000); // Each 5 seconds, display the current state of the items we have subscribed to. lock (_serialize) { Console.WriteLine(); foreach (KeyValuePair<DAItemDescriptor, DAVtqResult> pair in _vtqResultDictionary) { DAItemDescriptor itemDescriptor = pair.Key; DAVtqResult vtqResult = pair.Value; Console.WriteLine($"{itemDescriptor}: {vtqResult}"); } // The code above shows how you can process the complete contents of the dictionary. In other // scenarios, you may want to access just a specific entry in the dictionary. You can achieve that // by indexing the dictionary by the item descriptor of the item you are interested in. } } while (Environment.TickCount < startTickCount + 60*1000); Console.WriteLine("Unsubscribing item changes..."); } Console.WriteLine("Finished."); } // Item changed event handler static void client_ItemChanged_StoreInDictionary(object sender, EasyDAItemChangedEventArgs e) { lock (_serialize) // Convert the event arguments to a DAVtq result object, and store it in the dictionary under the key which // is the item descriptor of the item this item changed event is for. _vtqResultDictionary[e.Arguments.ItemDescriptor] = (DAVtqResult)e; } // Holds last known state of each subscribed item. private static readonly Dictionary<DAItemDescriptor, DAVtqResult> _vtqResultDictionary = new Dictionary<DAItemDescriptor, DAVtqResult>(); // Synchronization object used to prevent simultaneous access to the dictionary. private static readonly object _serialize = new object(); } }
# This example shows how to store current state of the subscribed items in a dictionary. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import threading import time # Import .NET namespaces. from OpcLabs.EasyOpc.DataAccess import * from OpcLabs.EasyOpc.DataAccess.OperationModel import * lock = threading.Lock() vtqResultDictionary = {} # Item changed event handler. def itemChanged(sender, eventArgs): global lock global vtqResultDictionary with lock: # Convert the event arguments to a DAVtq result object, and store it in the dictionary under the key which # is the item descriptor of the item this item changed event is for. vtqResultDictionary[eventArgs.Arguments.ItemDescriptor] = EasyDAItemChangedEventArgs.ToDAVtqResult(eventArgs) # Instantiate the client object. client = EasyDAClient() # Hook events. client.ItemChanged += itemChanged print('Subscribing item changes...') handleArray = IEasyDAClientExtension.SubscribeMultipleItems(client, [ DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000, None), DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Ramp (1 min)', 1000, None), DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Sine (1 min)', 1000, None), DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Register_I4', 1000, None), ]) for i in range(len(handleArray)): print('handleArray[', i, ']: ', handleArray[i], sep='') print('Processing item change notifications for 1 minute...') endTime = time.time() + 60 while time.time() < endTime: time.sleep(5) # # Each 5 seconds, display the current state of the items we have subscribed to. with lock: print() print('Current state of the items:') for itemDescriptor, vtqResult in vtqResultDictionary.items(): print(itemDescriptor, ': ', vtqResult, sep='') # # The code above shows how you can process the complete contents of the dictionary. In other # scenarios, you may want to access just a specific entry in the dictionary. You can achieve that # by indexing the dictionary by the item descriptor of the item you are interested in. print() print('Unsubscribing all items...') client.UnsubscribeAllItems() client.ItemChanged -= itemChanged print('Finished.')
' This example shows how to store current state of the subscribed items in a dictionary. Imports System.Threading Imports OpcLabs.EasyOpc.DataAccess Imports OpcLabs.EasyOpc.DataAccess.OperationModel Namespace DataAccess._EasyDAClient Partial Friend Class SubscribeMultipleItems Public Shared Sub StoreInDictionary() ' Instantiate the client object. Using client = New EasyDAClient() AddHandler client.ItemChanged, AddressOf client_ItemChanged_StoreInDictionary Console.WriteLine("Subscribing item changes...") client.SubscribeMultipleItems(New DAItemGroupArguments() { New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, Nothing), New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, Nothing), New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, Nothing), New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, Nothing) }) Console.WriteLine("Processing item changed events for 1 minute...") Dim startTickCount As Integer = Environment.TickCount Do Thread.Sleep(5 * 1000) ' Each 5 seconds, display the current state of the items we have subscribed to. SyncLock _serialize Console.WriteLine() For Each pair As KeyValuePair(Of DAItemDescriptor, DAVtqResult) In _vtqResultDictionary Dim itemDescriptor As DAItemDescriptor = pair.Key Dim vtqResult = pair.Value Console.WriteLine($"{itemDescriptor}: {vtqResult}") Next ' The code above shows how you can process the complete contents of the dictionary. In other ' scenarios, you may want to access just a specific entry in the dictionary. You can achieve that ' by indexing the dictionary by the item descriptor of the item you are interested in. End SyncLock Loop While Environment.TickCount < startTickCount + 60 * 1000 Console.WriteLine("Unsubscribing item changes...") End Using Console.WriteLine("Finished.") End Sub ' Item changed event handler Private Shared Sub client_ItemChanged_StoreInDictionary(ByVal sender As Object, ByVal e As EasyDAItemChangedEventArgs) SyncLock _serialize ' Convert the event arguments to a DAVtq result object, and store it in the dictionary under the key which ' is the item descriptor of the item this item changed event is for. _vtqResultDictionary(e.Arguments.ItemDescriptor) = CType(e, DAVtqResult) End SyncLock End Sub ' Holds last known state of each subscribed item. Private Shared ReadOnly _vtqResultDictionary As New Dictionary(Of DAItemDescriptor, DAVtqResult) ' Synchronization object used to prevent simultaneous access to the dictionary. Private Shared ReadOnly _serialize As New Object End Class End Namespace
Note: It is NOT an error to subscribe to the same item twice (or more times), even with precisely the same parameters. You will receive separate subscription handles, and with regard to your application, this situation will look no different from subscribing to different items. Internally, however, the subscription made to the OPC server will be optimized (merged together) if possible.
You can specify percent deadband when subscribing to an OPC item.
// This example shows how subscribe to changes of a single item with percent deadband. using System; using System.Diagnostics; using System.Threading; using OpcLabs.BaseLib.ComInterop; using OpcLabs.EasyOpc.DataAccess; namespace DocExamples.DataAccess._EasyDAClient { partial class SubscribeItem { public static void PercentDeadband() { // Instantiate the client object. var client = new EasyDAClient(); const float percentDeadband = 5.0f; Console.WriteLine($"Subscribing with {percentDeadband}% deadband..."); // The callback is a lambda expression the displays the value client.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Ramp 0:100 (10 s)", VarTypes.Empty, requestedUpdateRate:100, percentDeadband:percentDeadband, (sender, eventArgs) => { Debug.Assert(!(eventArgs is null)); if (eventArgs.Succeeded) { Debug.Assert(!(eventArgs.Vtq is null)); Console.WriteLine(eventArgs.Vtq.ToString()); } else Console.WriteLine("*** Failure: {0}", eventArgs.ErrorMessageBrief); }, state:null); Console.WriteLine("Processing item changed events for 10 seconds..."); Thread.Sleep(10 * 1000); Console.WriteLine("Unsubscribing..."); client.UnsubscribeAllItems(); Console.WriteLine("Waiting for 2 seconds..."); Thread.Sleep(2 * 1000); } } }
# This example shows how subscribe to changes of a single item with percent deadband. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.DataAccess import * # Item changed callback. def itemChangedCallback(sender, e): assert e is not None if e.Succeeded: assert e.Vtq is not None print(e.Vtq) else: print('*** Failure: ', e.ErrorMessageBrief, sep='') PERCENT_DEADBAND = 5.0 # Instantiate the client object. client = EasyDAClient() print('Subscribing item changes with ', PERCENT_DEADBAND, '% deadband...', sep='') # The callback is a regular method that displays the value. IEasyDAClientExtension.SubscribeItem(client, '', 'OPCLabs.KitServer.2', 'Simulation.Ramp 0:100 (10 s)', 50, EasyDAItemChangedEventHandler(itemChangedCallback)) print('Processing item change callbacks for 10 seconds...') time.sleep(10) print('Unsubscribing all items...') client.UnsubscribeAllItems() print('Waiting for 2 seconds...') time.sleep(2) print('Finished.')
You can also specify the percent deadband when subscribing to multiple OPC items, and the percent deadband can be different for each item.
// This example shows how subscribe to changes of multiple items with percent deadband. using System; using System.Threading; using OpcLabs.BaseLib.ComInterop; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace DocExamples.DataAccess._EasyDAClient { partial class SubscribeMultipleItems { public static void PercentDeadband() { // Instantiate the client object. using (var client = new EasyDAClient()) { client.ItemChanged += client_PercentDeadband_ItemChanged; Console.WriteLine("Subscribing with different percent deadbands..."); client.SubscribeMultipleItems( new[] { new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Ramp 0:100 (10 s)", VarTypes.Empty, requestedUpdateRate:100, percentDeadband:10.0f, null), new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Ramp 0:100 (1 min)", VarTypes.Empty, requestedUpdateRate:100, percentDeadband:5.0f, null), }); Console.WriteLine("Processing item changed events for 1 minute..."); Thread.Sleep(60 * 1000); } } // Item changed event handler static void client_PercentDeadband_ItemChanged(object sender, EasyDAItemChangedEventArgs e) { if (e.Succeeded) Console.WriteLine("{0}: {1}", e.Arguments.ItemDescriptor.ItemId, e.Vtq); else Console.WriteLine("{0} *** Failure: {1}", e.Arguments.ItemDescriptor.ItemId, e.ErrorMessageBrief); } } }
# This example shows how subscribe to changes of multiple items with percent deadband. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.BaseLib.ComInterop import * from OpcLabs.EasyOpc.DataAccess import * from OpcLabs.EasyOpc.DataAccess.OperationModel import * # Item changed event handler. def itemChanged(sender, e): if e.Succeeded: print(e.Arguments.ItemDescriptor.ItemId, ': ', e.Vtq, sep='') else: print(e.Arguments.ItemDescriptor.ItemId, ' *** Failure: ', e.ErrorMessageBrief, sep='') # Instantiate the client object. client = EasyDAClient() client.ItemChanged += itemChanged print('Subscribing item changes with different percent deadbands...') IEasyDAClientExtension.SubscribeMultipleItems(client, [ DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Ramp 0:100 (10 s)', VarType(VarTypes.Empty), 100, 10.0, None), DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Ramp 0:100 (1 min)', VarType(VarTypes.Empty), 100, 5.0, None), ]) print('Processing item change notifications for 1 minute...') time.sleep(60) print('Unsubscribing all items...') client.UnsubscribeAllItems() client.ItemChanged -= itemChanged print('Finished.')
The example below logs OPC Data Access item changes into an XML file.
The main program:
// Logs OPC Data Access item changes into an XML file. using System; using System.Diagnostics; using System.Xml; using System.Xml.Serialization; using OpcLabs.BaseLib.Runtime.InteropServices; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace XmlLogger { class Program { static void Main() { ComManagement.Instance.AssureSecurityInitialization(); Console.WriteLine("Starting up..."); var xmlSerializer = new XmlSerializer(typeof(EasyDAItemChangedEventArgs)); var xmlWriter = XmlWriter.Create("OpcData.xml", new XmlWriterSettings { Indent = true, CloseOutput = true }); // The root element can have any name you need, but the name below also allows reading the log back as .NET array xmlWriter.WriteStartElement("ArrayOfEasyDAItemChangedEventArgs"); Console.WriteLine("Logging data for 30 seconds..."); int handle = EasyDAClient.SharedInstance.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Incrementing (1 s)", 100, (_, eventArgs) => { Debug.Assert(!(eventArgs is null)); Console.Write("."); xmlSerializer.Serialize(xmlWriter, eventArgs); }); System.Threading.Thread.Sleep(30 * 1000); Console.WriteLine(); Console.WriteLine("Shutting down..."); EasyDAClient.SharedInstance.UnsubscribeItem(handle); xmlWriter.WriteEndElement(); // not really necessary - XmlWriter would write the end tag for us anyway xmlWriter.Close(); Console.WriteLine("Finished."); } } }
' Logs OPC Data Access item changes into an XML file. Imports System.Xml Imports System.Xml.Serialization Imports OpcLabs.BaseLib.Runtime.InteropServices Imports OpcLabs.EasyOpc.DataAccess Imports OpcLabs.EasyOpc.DataAccess.OperationModel Friend Class Program Shared WithEvents _client As New EasyDAClient Shared ReadOnly XmlSerializer As New XmlSerializer(GetType(EasyDAItemChangedEventArgs)) Shared _xmlWriter As XmlWriter <MTAThread> ' needed for COM security initialization to succeed Shared Sub Main() ComManagement.Instance.AssureSecurityInitialization() Console.WriteLine("Starting up...") _xmlWriter = XmlWriter.Create("OpcData.xml", New XmlWriterSettings With {.Indent = True, .CloseOutput = True}) ' The root element can have any name you need, but the name below also allows reading the log back as .NET array _xmlWriter.WriteStartElement("ArrayOfEasyDAItemChangedEventArgs") Console.WriteLine("Logging data for 30 seconds...") Dim handle As Integer = _client.SubscribeItem( "", "OPCLabs.KitServer.2", "Simulation.Incrementing (1 s)", 100) Threading.Thread.Sleep(30 * 1000) Console.WriteLine() Console.WriteLine("Shutting down...") _client.UnsubscribeItem(handle) _xmlWriter.WriteEndElement() ' not really necessary - XmlWriter would write the end tag for us anyway _xmlWriter.Close() Console.WriteLine("Finished.") End Sub Private Shared Sub ItemChanged(ByVal sender As Object, ByVal eventArgs As EasyDAItemChangedEventArgs) Handles _client.ItemChanged Debug.Assert(eventArgs IsNot Nothing) Console.Write(".") XmlSerializer.Serialize(_xmlWriter, eventArgs) End Sub End Class
Copyright © 2004-2023 CODE Consulting and Development, s.r.o., Plzen. All rights reserved. Web page: www.opclabs.com
Send Documentation Feedback. Resources: Knowledge Base. Technical support: Online Forums, FAQ.